﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using ClosedXML.Excel;

namespace HmLab.Func1;

internal class LbReadResultConfig {
  public class GroupAll(LbReadResultConfig _impl) {
    public DataGroupCfg[] Read(string path) => _impl.ReadGroupConfig(path);
  }
  public class AppConfig(LbReadResultConfig _impl) {
    public AppConfigRoot Read(DataGroupCfg[] groupAll, string dataDir) => _impl.ReadAppConfig(groupAll, dataDir);
  }

  public void Run() {
    Console.WriteLine("-------LbReadResultConfigLbReadResultConfigLbReadResultConfig");

    string headerPath = @"E:\work_etc\nina\2023haimen2\workshop_cslab\输Q出\数据源_新.xlsx";
    DataGroupCfg[] groupList = ReadGroupConfig(headerPath);
    //foreach (var grp in groupList) {
    //  Console.WriteLine(grp.Name);
    //  foreach (var head in grp.Header) {
    //    Console.WriteLine("-" + head);
    //  }
    //}

    //string lookupPath = @"E:\work_etc\nina\2023haimen2\workshop_cslab\输O入test\dev\vlookup.xlsx";
    string lookupPath = @"E:\work_etc\nina\2023haimen2\workshop_cs\haimen\resources\func1\vlookup.xlsx";
    Debug.Assert(File.Exists(lookupPath));

    AppConfigRoot appConfig = ReadAppConfig(groupList, lookupPath);
    foreach (var row in appConfig.Lookup) {
      Console.WriteLine(row.Key + " " + row.Value);
    }
  }

  /// <summary>
  /// <see cref="Haimen.AppConfigReader"/>
  /// </summary>
  AppConfigRoot ReadAppConfig(DataGroupCfg[] groupAll, string lookupPath) {
    Dictionary<string, DataHeaderCfg[]> headerDict =
      groupAll.ToDictionary(g => g.Name, g => g.Header);

    using FileStream stream = _excelUtil.OpenRead(lookupPath);
    using XLWorkbook lookupBook = new(stream);

    IXLWorksheet sheet = lookupBook.Worksheet(1);
    Dictionary<string, string> lookupDict = MakeLookupDict(sheet);
    return new(headerDict, lookupDict);
  }

  Dictionary<string, string> MakeLookupDict(IXLWorksheet sheet) {
    var CellStr = (int r, int c) => sheet.Cell(r, c).GetString();

    return Enumerable
      .Range(1, LastRowNum(sheet))
      .ToDictionary(r => CellStr(r, 1), r => CellStr(r, 2));
  }
  int LastRowNum(IXLWorksheet sheet) => _excelUtil.LastRowNum(sheet);

  #region Group
  DataGroupCfg[] ReadGroupConfig(string path) {
    using FileStream stream = _excelUtil.OpenRead(path);
    using XLWorkbook resultBook = new(stream);

    return resultBook.Worksheets
      .Select(MakeGroupCfg)
      .ToArray();
  }

  DataGroupCfg MakeGroupCfg(IXLWorksheet sheet) {
    IXLRow headerRow = sheet.Row(1);
    int lastCol = headerRow.LastCellUsed(XLCellsUsedOptions.All)
      .WorksheetColumn()
      .ColumnNumber();

    DataHeaderCfg[] headerList = Enumerable.Range(1, lastCol)
      .Select(c => headerRow.Cell(c))
      .Select(c => MakeHeaderCfg(c.GetText()))
      .ToArray();

    return new(sheet.Name, headerList);
  }

  DataHeaderCfg MakeHeaderCfg(string configStr) {
    string[] configSplit = configStr.Split('_');
    string name = configSplit[0];
    if (configSplit.Length == 1) {
      return new(name, HeaderColFunc.KEY);
    }

    HeaderColFunc func = configSplit[1] switch {
      "sum" => HeaderColFunc.SUM,
      "count" => HeaderColFunc.COUNT,
      _ => HeaderColFunc.VLOOKUP,
    };

    return new(name, func);
  }
  #endregion

  readonly MergeExcelUtils _excelUtil = new();
}

internal enum HeaderColFunc { KEY, SUM, VLOOKUP, COUNT }
internal record DataHeaderCfg(string Name, HeaderColFunc Func);
internal record DataGroupCfg(string Name, DataHeaderCfg[] Header);

internal record AppConfigRoot(
  Dictionary<string, DataHeaderCfg[]> Header, Dictionary<string, string> Lookup);
